const test_DeclarationVariable_1 = () => {

    const code = ` var a = 99
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: "var", tokenType: TokenType.keyword},
        {tokenValue: "a", tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 99, tokenType: TokenType.number},
        {tokenValue: ";", tokenType: TokenType.semicolon},
    ]
    const result = parser(tokenList, 0)

    const expect = [{

        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            type: TokenType.variable,
            value:"a",
        },
        value: {
            type: TokenType.number,
            value: 99,
        }
    }]
    ensure(equals(result, expect), '### test_DeclarationVariable_1')
}

const test_expression_object = () => {
    const code = `var o = {
        test: 123,
    }`
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: 'var', tokenType: TokenType.keyword},
        {tokenValue: 'o', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: '{', tokenType: TokenType.curlyLeft},

        {tokenValue: "test", tokenType: TokenType.variable},
        {tokenValue: ':', tokenType: TokenType.colon},
        {tokenValue: 123, tokenType: TokenType.number},
        {tokenValue: ",", tokenType: TokenType.comma},

        {tokenValue: "}", tokenType: TokenType.curlyRight},
    ]
    const result = parser(tokenList, 0)

    const expect = [{
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            type: TokenType.variable,
            value:"o",
        },
        value: {
            type: AstType.ExpressionObject,
            properties: [
                {
                    type: AstType.PropertyObject,
                    key: {
                        type: TokenType.variable,
                        value: 'test',
                    },
                    value: {
                        type: TokenType.number,
                        value: 123,
                    }
                }
            ],
        }

    }]
    ensure(equals(result, expect), '### test_expression_object')
}


const test_expression_function = () => {
    const code = `var f = function(a, b){
        var x = 1
    }`
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: "var", tokenType: TokenType.keyword},
        {tokenValue: 'f', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 'function', tokenType: TokenType.keyword},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 'a', tokenType: TokenType.variable},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 'b', tokenType: TokenType.variable},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
        {tokenValue: '{', tokenType: TokenType.curlyLeft},

        {tokenValue: "var", tokenType: TokenType.keyword},
        {tokenValue: 'x', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 10, tokenType: TokenType.number},
        {tokenValue: ";", tokenType: TokenType.semicolon},

        {tokenValue: '}', tokenType: TokenType.curlyRight},
    ]
    const result = parser(tokenList, 0)

    const expect = [{
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            type: TokenType.variable,
            value:"f",
        },
        value:{
            // 函数类型
            type: AstType.ExpressionFunction,
            // 参数列表
            params: [
                {
                    type: TokenType.variable,
                    value: 'a',
                },
                {
                    type: TokenType.variable,
                    value: 'b',
                },
            ],
            body: {
                type: AstType.StatementBlock,
                body: [
                    // 函数体是一条条语句组成的，所以是数组
                    {
                        type: AstType.DeclarationVariable,
                        kind: 'var',
                        variable: {
                            type: TokenType.variable,
                            value:"x",
                        },
                        value: {
                            type: TokenType.number,
                            value: 10,
                        }
                    },
                ]
            },
        },
    }]
    ensure(equals(result, expect), '### test_expression_function')
}

// 函数调用
const test_expression_function_call = () => {
    const code = `
        add(1, 2)
    `

    const tokenList = [
        {tokenValue: "add", tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
    ]
    const result = parser(tokenList, 0)

    const expect = [{
        type: AstType.ExpressionCall,
        // 被调用的函数名
        callee: {
            type: TokenType.variable,
            value: 'add',
        },
        // 参数
        arguments: [
            {
                type: TokenType.number,
                value: 1,
            },
            {
                type: TokenType.number,
                value: 2,
            },
        ],
    }]
    ensure(equals(result, expect), '### test_expression_function_call')
}
// 赋值表达式
const test_expression_assignment = () => {
    const code = `
        a = 9
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: "a", tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 9, tokenType: TokenType.number},
    ]
    const result = parser(tokenList, 0)

    const expect = [
        {
            type: AstType.ExpressionAssignment,
            left: {
                type: TokenType.variable,
                value: 'a',
            },
            right: {
                type: TokenType.number,
                value: 9,
            }
        }
    ]
    ensure(equals(result, expect), '### test_expression_function_call')
}

// 类定义
const test_expression_class = () => {
    const code = `
        var a = class() {
        }
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: "var", tokenType: TokenType.keyword},
        {tokenValue: 'a', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 'class', tokenType: TokenType.keyword},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
        {tokenValue: '{', tokenType: TokenType.curlyLeft},
        {tokenValue: '}', tokenType: TokenType.curlyRight},

    ]

    const expect = [{
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            type: TokenType.variable,
            value:"a",
        },
        value: {
            type: AstType.ExpressionClass,
            body: {
                type: AstType.StatementBlock,
                body: []
            },
        }
    }]
    // log("finally expect", expect)
    const result = parser(tokenList, 0)

    ensure(equals(result, expect), '### test_expression_class')
}


// 数组定义
const test_expression_array = () => {
    const code = `
        var arr = [1, 2, 3]
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: "var", tokenType: TokenType.keyword},
        {tokenValue: 'arr', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: '[', tokenType: TokenType.bracketLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 3, tokenType: TokenType.number},
        {tokenValue: ']', tokenType: TokenType.bracketRight},
    ]
    const result = parser(tokenList, 0)

    const expect = [{
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            type: TokenType.variable,
            value:"arr",
        },
        value: {
            type: AstType.ExpressionArray,
            elements: [
                {
                    type: TokenType.number,
                    value: 1,
                },
                {
                    type: TokenType.number,
                    value: 2,
                },
                {
                    type: TokenType.number,
                    value: 3,
                },
            ]
        }
    }]
    ensure(equals(result, expect), '### test_expression_array')
}

// 二元运算表达式
const test_expression_binary = () => {
    const code = `
       var a = 1 + a
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: "var", tokenType: TokenType.keyword},
        {tokenValue: 'a', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 'a', tokenType: TokenType.variable},
        {tokenValue: ';', tokenType: TokenType.semicolon},

    ]
    const result = parser(tokenList, 0)

    const expect =  [{
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            type: TokenType.variable,
            value:"a",
        },
        value: {
            type: AstType.ExpressionBinary,
            operator: {
                type: TokenType.plus,
                value: '+',
            },
            left: {
                type: TokenType.number,
                value: 1,
            },
            right: {
                type: TokenType.variable,
                value: 'a',
            },
        }
    }]
    ensure(equals(result, expect), '### test_expression_binary')
}

// 数组访问
const test_access_array = () => {
    const code = `
       a[1]
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: 'a', tokenType: TokenType.variable},
        {tokenValue: '[', tokenType: TokenType.bracketLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ']', tokenType: TokenType.bracketRight},
    ]
    const expect = [{
        type: AstType.ExpressionMember,
        object: {
            type: TokenType.variable,
            value: 'a',
        },
        // 相当于a.1
        property: {
            type: TokenType.number,
            value: 1,
        }
    }]
    const result = parser(tokenList, 0)

    ensure(equals(result, expect), '### test_access_array')
}

// 类变量访问
const test_expression_class_variable = () => {
    const code = `
       this.a = 1
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: 'this', tokenType: TokenType.variable},
        {tokenValue: '.', tokenType: TokenType.dot},
        {tokenValue: 'a', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 1, tokenType: TokenType.number},
    ]
    const result = parser(tokenList, 0)

    const expect = {
        type: AstType.ExpressionAssignment,
        operator: {
            type: TokenType.assign,
            value: '='
        },
        left: {
            type: AstType.ExpressionMember,
            object: {
                type: TokenType.variable,
                value: "this",
            },
            property: {
                type: TokenType.variable,
                value: 'a',
            }
        },
        right: {
            type: TokenType.number,
            value: 1,
        },
    }
    ensure(equals(result, expect), '### test_expression_class_variable')
}


// 类方法访问
const test_expression_class_function_call = () => {
    const code = `
       item.log(1, 2)
    `
    // const tokenList = new TokenList(code)

    const tokenList = [
        {tokenValue: 'item', tokenType: TokenType.variable},
        {tokenValue: '.', tokenType: TokenType.dot},
        {tokenValue: 'log', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
    ]
    const result = parser(tokenList, 0)

    const expect = {
        type: AstType.ExpressionCall,
        callee: {
            type: AstType.ExpressionMember,
            object: {
                type: TokenType.variable,
                value: "item",
            },
            property: {
                type: TokenType.variable,
                value: 'log',
            },
        },
        arguments: [
            {
                type: TokenType.number,
                value: 1,
            },
            {
                type: TokenType.number,
                value: 2,
            },
        ]
    }
    ensure(equals(result, expect), '### test_expression_class_function_call')
}

